<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import SvgIcon from '@/components/SvgIcon.vue'
import MessageItem from '@/views/content/MessageItem.vue'
import { fetchStream } from '@/util/fetch-stream'
import send from '@/assets/icon/send.svg'
import file from '@/assets/icon/file.svg'

const textarea = ref<HTMLTextAreaElement | null>(null)
const userMessage = ref('')
const contentBottomWidth = ref('50%')
const sendDisable = ref<boolean>(false)

const messages = ref<MessageItemObj[]>([
  {
    role: 'assistant',
    content: '你好，有什么能帮您的吗？'
  }
])

// 调整textarea高度的函数
function adjustHeight() {
  if (textarea.value) {
    textarea.value.style.height = 'auto'
    const newHeight = Math.max(30, Math.min(textarea.value.scrollHeight, 200))
    textarea.value.style.height = `${newHeight}px`
    textarea.value.style.overflowY = newHeight === 200 ? 'auto' : 'hidden'
  }
}

// 监听textarea的输入事件来调整高度
const handleInput = adjustHeight


const isMessageEmpty = computed(() => userMessage.value.trim() === '')

const chat = async (question: string, clear: boolean) => {
  sendDisable.value = true
  try {
    const ctrlAbout = new AbortController()
    const response = await fetch(`/api/chat`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: '*./*'
      },
      signal: ctrlAbout.signal,
      body: JSON.stringify({
        'question': question,
        'history_list': messages.value
      })
    })

    if (response.status !== 200) {
      console.error('fetch response.status:', response.status)
      return
    }

    // 添加消息
    messages.value.push(
      { role: 'user', content: question },
      { role: 'assistant', content: '' }
    )

    // 清除文本框内容
    if (clear) userMessage.value = ''

    const markdownParse = (text: string, sources: Source[]) => {
      return text
        .replace(/\[\[([cC])itation/g, '[citation')
        .replace(/[cC]itation:(\d+)]]/g, 'citation:$1]')
        .replace(/\[\[([cC]itation:\d+)]](?!])/g, `[$1]`)
        .replace(/\[[cC]itation:(\d+)]/g, (match, p1, _) => {
          const url = sources[parseInt(p1) - 1]['url']  // 从sources对象中获取URL
          return url ? `[\`${p1}\`](${url})` : match  // 如果有URL则替换，否则不变
        })
    }

    let sources: Source[] = []
    let chunks = ''

    fetchStream(
      response,
      {
        onChunk: (chunk) => {
          chunks += new TextDecoder().decode(chunk, { stream: true })
          if (chunks.includes('__LLM_RESPONSE__')) {
            const [sources_str, llm_response] = chunks.split('__LLM_RESPONSE__')
            if (!sources.length) {
              try {
                sources = JSON.parse(sources_str) as Source[]
                messages.value[messages.value.length - 1].sources = sources
              } catch (e) {
                console.error('sources error', e)
              }
            }
            const content = llm_response.includes('__MORE_QUESTIONS__')
              ? llm_response.split('__MORE_QUESTIONS__')[0]
              : llm_response
            messages.value[messages.value.length - 1].content = markdownParse(content, sources)
          }
        },
        onDone: () => {
          // 猜你想问
          const [_, moreQuestions] = chunks.split('__MORE_QUESTIONS__')
          try {
            messages.value[messages.value.length - 1].moreQuestions = JSON.parse(moreQuestions.trim().replace(/'/g, '"'))
          } catch (e) {
            messages.value[messages.value.length - 1].moreQuestions = []
          }
        }
      }
    )
  } finally {
    sendDisable.value = false
  }

}

const handleTextareaKeydown = (event: KeyboardEvent) => {
  if (event.key === 'Enter') {
    if (event.shiftKey) {
      // 插入换行符
      const textarea = event.target as HTMLTextAreaElement
      const start = textarea.selectionStart
      const end = textarea.selectionEnd
      userMessage.value =
        userMessage.value.substring(0, start) +
        userMessage.value.substring(end)
      textarea.selectionStart = textarea.selectionEnd = start + 1
    } else {
      // 阻止默认行为（换行）
      event.preventDefault()
      // 发送消息
      chat(userMessage.value, true)
    }
  }
}

// 获取浏览器宽高比
function getAspectRatio() {
  contentBottomWidth.value = window.innerWidth / window.innerHeight > 1 ? '50%' : '90%'
}


const scrollableHeight = computed(() => `calc(100% - ${Math.min(textarea.value?.scrollHeight || 0, 200)}px)`)

// 监听textareaValue的变化并调整高度
watch(userMessage, adjustHeight)

onMounted(() => {
  if (textarea.value) adjustHeight()
})
onMounted(() => {
  getAspectRatio()
})
onMounted(getAspectRatio)
watch(textarea, adjustHeight)

// 获取子组件的快捷问题
const handleQuickQuestions = (data: string) => {
  chat(data, false)
}
</script>

<template>
  <div class="content-container" style="height: calc(100% - 65px)">
    <div class="scrollable-content" :style="{ height: scrollableHeight }">
      <div v-for="(item,index) in messages" :key="index" class="message-itm">
        <MessageItem :data="item" @quickQuestion="handleQuickQuestions" />
      </div>
      <!-- 可滚动的内容 -->
    </div>
    <div class="content-bottom" :style="{width: contentBottomWidth}">
      <div class="fixed-action-bar">
        <SvgIcon :tooltipDisabled="false"
                 tooltipContent="上传不可用"
                 :imgSrc="file"
                 icon-size="25px"
                 :disable="true"
        />
        <textarea
          v-model="userMessage"
          ref="textarea"
          class="textarea"
          placeholder="Chat Message"
          @input="handleInput"
          rows="1"
          @keydown="handleTextareaKeydown"
        ></textarea>
        <div @click="isMessageEmpty ? null : chat(userMessage,true)">
          <SvgIcon tooltipContent="发送消息"
                   :disable="sendDisable"
                   :imgSrc="send"
                   icon-size="25px"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="less">
.content-container {
  height: 100%; // 或者可以设定为固定的高度
  box-sizing: border-box; // 确保padding计入总高度
  display: flex;
  flex-direction: column;
}

.scrollable-content {
  overflow-y: auto; // 当内容超过容器高度时出现滚动条
}

.content-bottom {
  margin: 0 auto;
  padding: 20px 0;
}

.fixed-action-bar {
  display: flex; // 使用flex布局水平排列子元素
  justify-content: center; // 子元素水平居中
  align-items: center; // 子元素垂直居中
  gap: 15px; // 子元素间距
  padding: 0 20px; // 内边距，增加些距离
  background-color: #fff; // 背景颜色
  border: 1px solid rgb(217, 217, 217);
  border-radius: 15px;
}

.textarea {
  flex-grow: 1;
  border: none;
  font-size: 16px;
  outline: none;
  resize: none;
  overflow-y: hidden;
  max-height: 200px;
  min-height: 30px;
  padding: 10px 0 0;

}

.message-itm {
}

</style>
